package com.aop.simple;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;

/**
 * @description 以warpper结尾的，后续都会标识为Aop处理方式
 * @Author longdeng
 * @Date 2020/8/26 0026 22:56
 */
@Component
@Aspect
@Slf4j
public class SimpleAopActionWrapper {

    /**
     * 真对于SimpleAopAction下的所有方法进行切面处理
     */
    @Pointcut("execution(* com.aop.simple.SimpleAopAction.*(..))")
    public void simpleAopActionPointCut() {
    }

    /**
     * 前置通知
     *
     * @param jp
     */
    @Before("simpleAopActionPointCut()")
    public void before(JoinPoint jp) {
        /**
         * 前置我需要获取，关于HttpServletRequest里面的信息
         *  访问的url地址
         *  类名
         *  方法名
         *  参数列表
         */
        ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
        HttpServletRequest request = attrs.getRequest();
        StringBuffer url = request.getRequestURL();
        String className = jp.getThis().getClass().getName();
        String methodName = jp.getSignature().getName();
        Object[] args = jp.getArgs();
        log.info("==========================================访问前置==============================================");
        log.info("当前请求的url:{},类名:{},方法名:{},参数列表:{}", url, className, methodName, Arrays.toString(args));

    }

    /**
     * 环绕通知
     * 记录执行当前aop切面的方法的执行时间
     */
    @Around("simpleAopActionPointCut()")
    public void around(ProceedingJoinPoint jp) {
        /**
         * 统计aop切面方法执行的时间
         */
        try {
            // 开始时间
            long startTime = System.currentTimeMillis();
            jp.proceed();
            long endTime = System.currentTimeMillis();
            log.info("执行方法耗时:{}", (endTime - startTime));
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
    }

    /**
     * 后置通知
     */
    @After("simpleAopActionPointCut()")
    public void after(JoinPoint joinPoint) {
        /**
         * 我要拿到放到dto中的数据信息，比如公司的框架对象dto信息
         */
        ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
        HttpServletRequest request = attrs.getRequest();
        Object name = request.getAttribute("name");
        log.info("当前dto对象的中的数据信息为:{}", name);
    }

    /**
     * 后置返回通知
     */
    @AfterReturning("simpleAopActionPointCut()")
    public void afterReturn(JoinPoint joinPoint) {
        /**
         * 这个暂时不知道有什么意义
         */
        log.info("暂时afterReturn不做任何处理");
    }

    /**
     * 异常返回通知
     */
    @AfterThrowing(value = "simpleAopActionPointCut()", throwing = "e")
    public void afterThrowing(JoinPoint joinPoint, Throwable e) {
        log.info("当前异常的栈信息如下:{}", e.getMessage());
    }

}
